From 69bc3d055a38de18bba4d3b385ba16c3067f596f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Sep 2014 09:16:25 -0700 Subject: [PATCH] Allow specifying what to build as part of `cargo build` This allows selectively building one dependency within a dependency graph for debugging its build or such. Closes #537 --- src/bin/bench.rs | 1 + src/bin/build.rs | 12 ++++++++++-- src/bin/doc.rs | 1 + src/bin/run.rs | 1 + src/bin/test.rs | 1 + src/cargo/ops/cargo_compile.rs | 15 ++++++++++++--- src/cargo/ops/cargo_rustc/mod.rs | 14 +++++++++++--- tests/test_cargo_compile_path_deps.rs | 14 ++++++++++++++ 8 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/bin/bench.rs b/src/bin/bench.rs index 5448adfaf..9f9396cdb 100644 --- a/src/bin/bench.rs +++ b/src/bin/bench.rs @@ -42,6 +42,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: true, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, + spec: None, }, }; diff --git a/src/bin/build.rs b/src/bin/build.rs index 1a977920a..77047359c 100644 --- a/src/bin/build.rs +++ b/src/bin/build.rs @@ -11,7 +11,7 @@ docopt!(Options, " Compile a local package and all of its dependencies Usage: - cargo build [options] + cargo build [options] [] Options: -h, --help Print this message @@ -22,8 +22,15 @@ Options: --target TRIPLE Build for the target triple --manifest-path PATH Path to the manifest to compile -v, --verbose Use verbose output + +If is given, then only the package specified will be build (along with +all its dependencies). If is not given, then the current package will be +built. + +For more information about the format of , see `cargo help pkgid`. ", flag_jobs: Option, flag_target: Option, - flag_manifest_path: Option, flag_features: Vec) + flag_manifest_path: Option, flag_features: Vec, + arg_spec: Option) pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { debug!("executing; cmd=cargo-build; args={}", os::args()); @@ -45,6 +52,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: false, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, + spec: options.arg_spec.as_ref().map(|s| s.as_slice()), }; ops::compile(&root, &mut opts).map(|_| None).map_err(|err| { diff --git a/src/bin/doc.rs b/src/bin/doc.rs index a1c0beaf2..d06353598 100644 --- a/src/bin/doc.rs +++ b/src/bin/doc.rs @@ -41,6 +41,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: false, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, + spec: None, }, }; diff --git a/src/bin/run.rs b/src/bin/run.rs index afd3a27b0..f52a1e5aa 100644 --- a/src/bin/run.rs +++ b/src/bin/run.rs @@ -38,6 +38,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: true, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, + spec: None, }; let err = try!(ops::run(&root, &mut compile_opts, diff --git a/src/bin/test.rs b/src/bin/test.rs index 9f6d74738..cfecce9cd 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -41,6 +41,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: true, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, + spec: None, }, }; diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 6962f5fd9..cfd82c028 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -41,12 +41,13 @@ pub struct CompileOptions<'a> { pub dev_deps: bool, pub features: &'a [String], pub no_default_features: bool, + pub spec: Option<&'a str>, } pub fn compile(manifest_path: &Path, options: &mut CompileOptions) -> CargoResult { - let CompileOptions { env, ref mut shell, jobs, target, + let CompileOptions { env, ref mut shell, jobs, target, spec, dev_deps, features, no_default_features } = *options; let target = target.map(|s| s.to_string()); let features = features.iter().flat_map(|s| { @@ -102,7 +103,15 @@ pub fn compile(manifest_path: &Path, debug!("packages={}", packages); - let targets = package.get_targets().iter().filter(|target| { + let to_build = match spec { + Some(spec) => { + let pkgid = try!(resolve_with_overrides.query(spec)); + packages.iter().find(|p| p.get_package_id() == pkgid).unwrap() + } + None => &package, + }; + + let targets = to_build.get_targets().iter().filter(|target| { match env { // doc-all == document everything, so look for doc targets "doc" | "doc-all" => target.get_profile().get_env() == "doc", @@ -115,7 +124,7 @@ pub fn compile(manifest_path: &Path, let mut config = try!(Config::new(*shell, jobs, target)); try!(scrape_target_config(&mut config, &user_configs)); - try!(ops::compile_targets(env.as_slice(), targets.as_slice(), &package, + try!(ops::compile_targets(env.as_slice(), targets.as_slice(), to_build, &PackageSet::new(packages.as_slice()), &resolve_with_overrides, &sources, &mut config)) diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 307743177..dd00134cf 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -60,9 +60,10 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package, debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps); let dest = uniq_target_dest(targets); - let host_layout = Layout::new(pkg, None, dest); + let root = deps.iter().find(|p| p.get_package_id() == resolve.root()).unwrap(); + let host_layout = Layout::new(root, None, dest); let target_layout = config.target().map(|target| { - layout::Layout::new(pkg, Some(target), dest) + layout::Layout::new(root, Some(target), dest) }); let mut cx = try!(Context::new(env, resolve, sources, deps, config, @@ -76,8 +77,13 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package, // particular package. No actual work is executed as part of this, that's // all done later as part of the `execute` function which will run // everything in order with proper parallelism. + let mut dep_pkgids = HashSet::new(); + each_dep(pkg, &cx, |dep| { + dep_pkgids.insert(dep.get_package_id().clone()); + }); for dep in deps.iter() { if dep == pkg { continue } + if !dep_pkgids.contains(dep.get_package_id()) { continue } // Only compile lib targets for dependencies let targets = dep.get_targets().iter().filter(|target| { @@ -91,7 +97,9 @@ pub fn compile_targets<'a>(env: &str, targets: &[&'a Target], pkg: &'a Package, try!(compile(targets.as_slice(), dep, &mut cx, &mut queue)); } - cx.primary(); + if pkg.get_package_id() == resolve.root() { + cx.primary(); + } try!(compile(targets, pkg, &mut cx, &mut queue)); // Now that we've figured out everything that we're going to do, do it! diff --git a/tests/test_cargo_compile_path_deps.rs b/tests/test_cargo_compile_path_deps.rs index d784341ca..1edd24c69 100644 --- a/tests/test_cargo_compile_path_deps.rs +++ b/tests/test_cargo_compile_path_deps.rs @@ -83,6 +83,20 @@ test!(cargo_compile_with_nested_deps_shorthand { assert_that( cargo::util::process(p.bin("foo")), execs().with_stdout("test passed\n")); + + println!("cleaning"); + assert_that(p.process(cargo_dir().join("cargo")).arg("clean"), + execs().with_stdout("")); + println!("building baz"); + assert_that(p.process(cargo_dir().join("cargo")).arg("build").arg("baz"), + execs().with_stdout(format!("{} baz v0.5.0 ({})\n", + COMPILING, p.url()))); + println!("building foo"); + assert_that(p.process(cargo_dir().join("cargo")).arg("build").arg("foo"), + execs().with_stdout(format!("{} bar v0.5.0 ({})\n\ + {} foo v0.5.0 ({})\n", + COMPILING, p.url(), + COMPILING, p.url()))); }) test!(cargo_compile_with_root_dev_deps { -- 2.30.2